const { Service } = require('egg');
const myDate = require('../utils/myDate');
const { sendEmail } = require('../utils/email');
const { emailThrottleDuration } = require('../config/index');

class ExamService extends Service {
  async addTestPaper(testPaperInfo) {
    testPaperInfo.create_time = myDate.getNowDate();
    testPaperInfo.update_time = myDate.getNowDate();
    const token = this.ctx.request.header.authorization?.slice(7);
    const userInfo = this.app.jwt.decode(token);
    testPaperInfo.create_by = userInfo.id;
    testPaperInfo.update_by = userInfo.id;
    delete testPaperInfo.id;
    let sumScore = 0;
    const contentNoAnswer = [];
    for (let i = 0; i < testPaperInfo.content.length; i++) {
      let quesSumScore = 0;
      contentNoAnswer.push({
        title: testPaperInfo.content[i].title,
        sumScore: testPaperInfo.content[i].sumScore,
        ques: [],
      });
      for (let j = 0; j < testPaperInfo.content[i].ques.length; j++) {
        quesSumScore += testPaperInfo.content[i].ques[j].score;
        contentNoAnswer[i].ques.push({
          ...testPaperInfo.content[i].ques[j],
          answer: '',
        });
      }
      testPaperInfo.content[i].sumScore = quesSumScore;
      sumScore += quesSumScore;
    }
    testPaperInfo.score = sumScore;
    testPaperInfo.content = JSON.stringify(testPaperInfo.content);
    testPaperInfo.content_no_answer = JSON.stringify(contentNoAnswer);
    const res = await this.app.mysql.insert('exam_paper', testPaperInfo);
    if (res.affectedRows) {
      return {
        state: true,
        msg: res.insertId,
      };
    }
    return {
      state: false,
      msg: '添加失败',
    };
  }

  async updateTestPaper(testPaperInfo) {
    const isExit = await this.app.mysql.get('exam_paper', { id: testPaperInfo.id });
    if (!isExit) {
      return {
        state: false,
        msg: '试卷不存在',
      };
    }
    // 保证创建态不被修改
    testPaperInfo.create_time = isExit.create_time;
    testPaperInfo.create_by = isExit.create_by;
    testPaperInfo.update_time = myDate.getNowDate();
    const token = this.ctx.request.header.authorization?.slice(7);
    const userInfo = this.app.jwt.decode(token);
    testPaperInfo.update_by = userInfo.id;
    let sumScore = 0;
    const contentNoAnswer = [];
    for (let i = 0; i < testPaperInfo.content.length; i++) {
      let quesSumScore = 0;
      contentNoAnswer.push({
        title: testPaperInfo.content[i].title,
        sumScore: testPaperInfo.content[i].sumScore,
        ques: [],
      });
      for (let j = 0; j < testPaperInfo.content[i].ques.length; j++) {
        for (let tk = 0; tk < testPaperInfo.content[i].ques[j].data.length; tk++) {
          if (testPaperInfo.content[i].ques[j].data[tk].type === 'fillBlank') {
            testPaperInfo.content[i].ques[j].data[tk].content = new Array(testPaperInfo.content[i].ques[j].data[tk].content.length).fill({ value: '' });
          }
        }
        contentNoAnswer[i].ques.push({
          ...testPaperInfo.content[i].ques[j],
          answer: '',
        });
        quesSumScore += testPaperInfo.content[i].ques[j].score;
      }
      testPaperInfo.content[i].sumScore = quesSumScore;
      sumScore += quesSumScore;
    }
    testPaperInfo.score = sumScore;
    testPaperInfo.content = JSON.stringify(testPaperInfo.content);
    testPaperInfo.content_no_answer = JSON.stringify(contentNoAnswer);
    const res = await this.app.mysql.update('exam_paper', testPaperInfo);
    if (res.affectedRows > 0) {
      return {
        state: true,
        msg: '更新成功',
      };
    }
    return {
      state: false,
      msg: '更新失败',
    };

  }

  async delTestPaper(ids) {
    const res = await this.app.mysql.query(
      `delete from exam_paper where id in (${ids.join(',')})`
    );
    if (res.affectedRows) {
      return {
        state: true,
        msg: '删除成功',
      };
    }
    return {
      state: false,
      msg: '删除失败',
    };
  }

  async getTestPaper(id) {
    const res = await this.app.mysql.get('exam_paper', { id });
    if (res) {
      res.content = JSON.parse(res.content);
      return res;
    }
    return false;
  }


  async getTestPapers(pageNum, pageSize, name) {
    if (!pageNum) {
      pageNum = 1;
    }
    if (!pageSize) {
      pageSize = 10;
    }
    let where = '';
    if (name) {
      where = `WHERE name LIKE '%${name}%'`;
    }
    const total = await this.app.mysql.count('exam_paper');
    const res = await this.app.mysql.query(`SELECT * FROM exam_paper ${where} LIMIT ?, ?`, [ (pageNum - 1) * pageSize, pageSize ]);
    if (res) {
      return {
        ques: res,
        total,
      };
    }
    return false;
  }

  async addExam(testInfo) {
    testInfo.create_time = myDate.getNowDate();
    testInfo.update_time = myDate.getNowDate();
    const token = this.ctx.request.header.authorization?.slice(7);
    const userInfo = this.app.jwt.decode(token);
    testInfo.create_by = userInfo.id;
    testInfo.update_by = userInfo.id;
    const res = await this.app.mysql.insert('exam', {
      name: testInfo.name,
      begin: testInfo.begin,
      end: testInfo.end,
      duration: testInfo.duration,
      is_limit_jump: 1,
      limit_jump_times: 5,
      screen_recording: 0,
      face_recording: 0,
      create_by: userInfo.id,
      update_by: userInfo.id,
      create_time: myDate.getNowDate(),
      update_time: myDate.getNowDate(),
    });
    if (res.affectedRows) {
      return true;
    }
    return false;
  }

  async getExam(id) {
    const exam = await this.app.mysql.get('exam', { id });
    if (exam) {
      const users = await this.app.mysql.query(
        `SELECT u.* 
        FROM exam_user eu 
        JOIN user u ON u.id = eu.user_id
        where eu.exam_id = ${exam.id}`
      );
      const tests = await this.app.mysql.query(
        `SELECT *
        FROM exam_user eu 
        JOIN user u ON u.id = eu.user_id
        WHERE eu.exam_id = ${exam.id}`
      );
      const papers = await this.app.mysql.query(
        `SELECT * 
        from exam_paper_link epl
        JOIN exam_paper ep ON ep.id = epl.paper_id
        WHERE epl.exam_id = ${exam.id}
`
      );
      return {
        users,
        exam,
        tests,
        papers,
      };
    }
    return false;
  }

  async getExams(pageNum, pageSize, name) {
    let where = '';
    if (name) {
      where = `WHERE name LIKE '%${name}%'`;
    }
    const total = await this.app.mysql.count('exam', where);
    const res = await this.app.mysql.query(
      `SELECT * FROM exam ${where} LIMIT ?, ?`,
      [ (pageNum - 1) * pageSize, pageSize ]
    );
    if (res) {
      return {
        meetings: res,
        total,
      };
    }
    return false;
  }

  async updateExam(examInfo) {
    const isExit = await this.app.mysql.get('exam', { id: examInfo.id });
    if (!isExit) {
      return {
        state: false,
        msg: '考试不存在',
      };
    }
    examInfo.update_time = myDate.getNowDate();
    const token = this.ctx.request.header.authorization?.slice(7);
    const userInfo = this.app.jwt.decode(token);
    const res = await this.app.mysql.update('exam', {
      id: examInfo.id,
      name: examInfo.name,
      begin: examInfo.begin,
      end: examInfo.end,
      duration: examInfo.duration,
      update_by: userInfo.id,
    });
    if (res.affectedRows > 0) {
      return true;
    }
    return false;
  }

  async addExamUser(examId, userIds) {
    for (const id of userIds) {
      const isExit = await this.app.mysql.query(
        `SELECT * FROM exam_user WHERE exam_id = ${examId} AND user_id = ${id}`
      );
      if (isExit.length) {
        continue;
      }
      const res = await this.app.mysql.query(
        `INSERT INTO exam_user (exam_id, user_id) VALUES (${examId}, ${id})`
      );
      if (!res) {
        return {
          state: false,
          msg: '添加失败',
        };
      }
    }
    await this.ctx.service.exam.updateExams(examId);
    return {
      state: true,
      msg: '添加成功',
    };
  }

  async updateExams(examId) {
    const curUser = await this.app.mysql.query(
      `SELECT user_id FROM exam_user WHERE exam_id = ${examId}`
    );
    const userIds = curUser.map(item => item.user_id);
    if (userIds.length) {
      await this.app.mysql.query(
        `delete from exam_user where exam_id = ${examId} and user_id not in (${userIds.join(
        )})`
      );
    } else {
      await this.app.mysql.query(
        `delete from exam_user where exam_id = ${examId}`
      );
      return;
    }
    for (let i = 0; i < userIds.length; i++) {
      const isExit = await this.app.mysql.query(
        `SELECT * FROM exam_user WHERE exam_id = ${examId} AND user_id = ${userIds[i]}`
      );
      if (isExit.length) {
        continue;
      }
      await this.app.mysql.query(
        `INSERT INTO exam_user (exam_id, user_id, state) VALUES (${examId}, ${userIds[i]}, '0')`
      );
    }
  }

  async delExamUsers(examId, userIds) {
    const res = await this.app.mysql.query(
      `delete from exam_user 
      where exam_id = ${examId} 
      and user_id in (${userIds.join(',')})`
    );
    await this.ctx.service.exam.updateExams(examId);
    if (res.affectedRows) {
      return true;
    }
    return false;
  }

  async sendEmail(examId, userId) {
    const isSend = await this.ctx.service.redis.get(`send-test-email${examId}${userId}`);
    if (isSend) {
      return {
        state: false,
        msg: '冷却中，请稍后再试试',
      };
    }
    const tests = await this.app.mysql.query(
      `SELECT * FROM exam WHERE id = ${examId}`
    );
    if (!tests[0].begin || !tests[0].end) {
      return {
        state: false,
        msg: '笔试时间未设置',
      };
    }
    const examPapers = await this.app.mysql.query(
      `SELECT * FROM exam_paper_link WHERE exam_id = ${examId}`
    );
    if (!examPapers.length) {
      return {
        state: false,
        msg: '笔试试卷未设置',
      };
    }
    await this.ctx.service.redis.set(`send-test-email${examId}${userId}`, true, emailThrottleDuration);
    const curTest = await this.app.mysql.query(
      `SELECT * FROM exam_user WHERE exam_id = ${examId} AND user_id = ${userId}`
    );
    let uniqueId = '';
    if (Number(curTest[0].is_send_email) !== 1) {
      uniqueId = this.app.jwt.sign({ id: userId, examId }, this.app.config.jwt.secret);
      await this.app.mysql.query(
        `UPDATE exam_user 
        SET is_send_email = '1', token = '${uniqueId}'
        WHERE exam_id = ${examId} AND user_id = ${userId};`
      );
    } else {
      uniqueId = curTest[0].token;
    }
    const userData = await this.app.mysql.query(
      `SELECT * FROM user WHERE id = ${userId}`
    );
    const userEmail = userData[0].email;
    const htmlContent = `
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>笔试邀请</title>
    </head>
    <body>
        <p>亲爱的${userData[0].name} 同学，您好！</p>
        <p>感谢关注PANDA校园招聘！现诚邀您参加${tests[0].name}职位的笔试。</p>
        <p>视笔试时请您尽量使用电脑端进行操作（大于73版本的Chrome内核浏览器或者firefox、opera浏览器），并打开相机权限。</p>
        <ul>
            <li>笔试日期：2025年3月4日星期二</li>
            <li>笔试时间：17:00</li>
            <li>笔试时长：45分钟</li>
            <li>笔试形式：在线笔试</li>
            <li>笔试地址：http://localhost:3001/#/login?key=${uniqueId}</li>
        </ul>
        <h3>【注意】</h3>
        <ol>
            <li>如确定参加面试，请点击“参加”。</li>
            <li>如时间冲突，请点击“拒绝”，并反馈可面试时间。</li>
        </ol>
        <p>有任何问题，请联系hr: 17338763009</p>
        <p>请您确认是否参加</p>
        <p>
        <a href="#" style="background-color: #007bff; color: white; padding: 10px 20px; text-decoration: none;">参加 / Yes</a> 
        <a href="#" style="background-color: #6c757d; color: white; padding: 10px 20px; text-decoration: none;">不参加 / No</a> 
        </p>
    </body>
    </html>
    `;
    const res = await sendEmail(userEmail, 'PANDA校园招聘——应届生面试邀请函', htmlContent);
    if (res) {
      return {
        state: true,
        msg: '发送成功',
      };
    }
    return {
      state: false,
      msg: '发送失败',
    };
  }

  async delExam(ids) {
    const res = await this.app.mysql.query(
      `delete from exam where id in (${ids.join(',')})`
    );
    await this.app.mysql.query(
      `delete from exam_user where exam_id in (${ids.join(',')})`
    );
    await this.app.mysql.query(
      `delete from exam_paper_link where exam_id in (${ids.join(',')})`
    );
    if (res.affectedRows) {
      return {
        state: true,
        msg: '删除成功',
      };
    }
    return {
      state: false,
      msg: '删除失败',
    };
  }

  async getNum() {
    const questionNum = await this.app.mysql.query(
      'SELECT COUNT(*) FROM ques'
    );
    const userNum = await this.app.mysql.query(
      'SELECT COUNT(*) FROM user'
    );
    const examNum = await this.app.mysql.query(
      'SELECT COUNT(*) FROM exam'
    );
    const testPaperNum = await this.app.mysql.query(
      'SELECT COUNT(*) FROM exam_paper'
    );
    return {
      questionNum: questionNum[0]['COUNT(*)'],
      userNum: userNum[0]['COUNT(*)'],
      examNum: examNum[0]['COUNT(*)'],
      testPaperNum: testPaperNum[0]['COUNT(*)'],
    };
  }

  async updateConfig(examId, is_limit_jump, face_recording, limit_jump_times, screen_recording) {
    const res = await this.app.mysql.update('exam', {
      id: examId,
      is_limit_jump,
      face_recording,
      limit_jump_times,
      screen_recording,
    });
    if (res.affectedRows) {
      return true;
    }
    return false;
  }

  async linkExamPaper(examId, testPaperIds) {
    await this.app.mysql.query(
      `delete from exam_paper_link where exam_id = ${examId}`
    );
    for (let i = 0; i < testPaperIds.length; i++) {
      const insertRes = await this.app.mysql.query(
        `INSERT INTO exam_paper_link (exam_id, paper_id) VALUES (${examId}, ${testPaperIds[i]})`
      );
      if (!insertRes) {
        return false;
      }
    }
    return true;
  }
}

module.exports = ExamService;

